package com.aizuda.boot.modules.business.counterparty.controller;


import cn.hutool.http.Header;
import com.aizuda.boot.modules.business.contract.dto.SingleResponse;
import com.aizuda.boot.modules.common.constant.enums.ResponseCodeEnum;
import com.aizuda.boot.modules.business.counterparty.entity.dto.*;
import com.aizuda.boot.modules.business.counterparty.entity.vo.ChangeRecordVO;
import com.aizuda.boot.modules.business.counterparty.entity.vo.CounterpartyPageRespDTO;
import com.aizuda.boot.modules.business.counterparty.entity.vo.CounterpartyVO;
import com.aizuda.boot.modules.business.counterparty.entity.vo.CreateCounterpartyRespDTO;
import com.aizuda.boot.modules.business.counterparty.service.CounterpartyService;
import com.aizuda.boot.modules.file.domain.entity.FileInfo;
import com.aizuda.boot.modules.file.domain.vo.FileDownloadVO;
import com.aizuda.boot.modules.file.service.FileInfoService;
import com.aizuda.boot.modules.file.util.FileResponseUtil;
import com.aizuda.core.api.ApiAssert;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.List;

/**
 * 交易方管理控制器
 */
@Slf4j
@RestController
@RequestMapping("/counterparty")
@Tag(description = "/counterparty", name = "交易方管理接口")
@Validated
public class CounterpartyController {

    @Resource
    private CounterpartyService counterpartyService;

    @Resource
    private FileInfoService fileService;

    @PostMapping("/page")
    @Operation(summary = "分页查询交易方列表")
    public SingleResponse<CounterpartyPageRespDTO> queryCounterpartiesPage(@RequestBody @Validated CounterpartyQueryReqDTO reqDTO) {
        try {
            log.info("分页查询交易方列表，请求参数：{}", reqDTO);
            CounterpartyPageRespDTO pageResult = counterpartyService.queryCounterpartiesPage(reqDTO);
            return SingleResponse.of(pageResult);
        } catch (Exception e) {
            log.error("分页查询交易方列表失败", e);
            return SingleResponse.failure(ResponseCodeEnum.SHOW_MSG.getCode(), "查询交易方列表失败: " + e.getMessage());
        }
    }

    @PostMapping("/create")
    @Operation(summary = "新增交易方")
    public SingleResponse<CreateCounterpartyRespDTO> createCounterparty(@RequestBody @Valid CreateCounterpartyReqDTO reqDTO, HttpServletRequest request) {
        try {
            log.info("新增交易方，请求参数：{}", reqDTO);
            CreateCounterpartyRespDTO result = counterpartyService.createCounterparty(reqDTO, request);
            return SingleResponse.of(result);
        } catch (Exception e) {
            log.error("新增交易方失败", e);
            return SingleResponse.failure(ResponseCodeEnum.SHOW_MSG.getCode(), "新增交易方失败: " + e.getMessage());
        }
    }

    @PostMapping("/checkUniqueness")
    @Operation(summary = "检查交易方唯一性")
    public SingleResponse<String> checkCounterpartyUniqueness(@RequestBody @Valid CounterpartyUniquenessReqDTO reqDTO) {
        try {
            log.info("检查交易方唯一性，请求参数：{}", reqDTO);
            boolean isUnique = counterpartyService.checkCounterpartyUniqueness(
                    reqDTO.getCounterpartyName(),
                    reqDTO.getRegisterCountry(),
                    reqDTO.getCounterpartyNature()
            );

            if (isUnique) {
                log.info("交易方唯一性检查结果：唯一，可以创建");
                return SingleResponse.of("交易方信息唯一，可以创建");
            } else {
                log.info("交易方唯一性检查结果：不唯一，已存在相同记录");
                return SingleResponse.failure(ResponseCodeEnum.SHOW_MSG.getCode(), "交易方已存在，相同的交易方名称、注册国家和交易方性质组合已被使用");
            }
        } catch (Exception e) {
            log.error("检查交易方唯一性失败", e);
            return SingleResponse.failure(ResponseCodeEnum.SHOW_MSG.getCode(), "检查交易方唯一性失败: " + e.getMessage());
        }
    }


    @PutMapping("/update")
    @Operation(summary = "修改交易方")
    public Boolean update(@RequestBody @Valid UpdateCounterpartyReqDTO reqDTO, HttpServletRequest request) {
        try {
            log.info("修改交易方，请求参数：{}", reqDTO);
            return counterpartyService.updateCounterparty(reqDTO, request);
        } catch (Exception e) {
            log.error("修改交易方失败", e);
            ApiAssert.fail("修改交易方失败" + e.getMessage());
            return false;
        }
    }


    @PostMapping("/toggleStatus")
    @Operation(summary = "修改交易方状态")
    public Boolean toggleStatus(@RequestBody @Validated UpdateStatusDTO reqDTO) {
        try {
            log.info("修改交易方状态，请求参数：{}", reqDTO);
            return counterpartyService.toggleCounterpartyStatus(reqDTO.getId(), reqDTO.getEnabled());
        } catch (Exception e) {
            log.error("修改交易方状态失败", e);
            ApiAssert.fail("修改交易方状态失败" + e.getMessage());
            return false;
        }
    }

    @GetMapping("changeRecords/{counterpartyId}")
    @Operation(summary = "查询交易方修改记录")
    public List<ChangeRecordVO> queryChangeRecords(@PathVariable Integer counterpartyId) {
        try {
            return counterpartyService.queryChangeRecords(counterpartyId);
        } catch (Exception e) {
            log.error("查询交易方修改记录失败", e);
            ApiAssert.fail("查询交易方修改记录失败" + e.getMessage());
            return null;
        }
    }

    @Operation(summary = "上传文件更新交易方")
    @PostMapping("/upload")
    public SingleResponse<Boolean> uploadCounterparty(@RequestBody MultipartFile file) {
        try {
            return counterpartyService.uploadCounterparty(file);
        } catch (Exception e) {
            log.error("上传文件更新交易方失败", e);
            return SingleResponse.failure(ResponseCodeEnum.ERROR.getCode(), ResponseCodeEnum.ERROR.getMsg());
        }

    }

    @Operation(summary = "下载交易方模板")
    @GetMapping("/downloadTemplate")
    public void downLoadTemplate(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String fileName = "交易方数据批量维护模板.xlsx";
        String resourcePath = "static/documents/" + fileName;

        ClassPathResource resource = new ClassPathResource(resourcePath);
        if (!resource.exists()) {
            FileResponseUtil.write(response, SingleResponse.failure(ResponseCodeEnum.SHOW_MSG.getCode(), "模板文件不存在: " + fileName));
            return;
        }

        long contentLength = resource.contentLength();
        FileResponseUtil.setDownloadFileHeader(response, fileName, contentLength);

        try (java.io.InputStream inputStream = resource.getInputStream()) {
            inputStream.transferTo(response.getOutputStream());
        }
    }


    @Operation(summary = "查询所有交易方列表")
    @GetMapping("/list")
    public List<CounterpartyVO> getCounterpartyList() {
        return counterpartyService.getCounterpartyList();
    }


    @Operation(summary = "查询交易方详情")
    @GetMapping("/{certificateId}")
    public SingleResponse<CounterpartyPageRespDTO.CounterpartyItemDTO> getById(@PathVariable String certificateId) {
        try {
            return SingleResponse.of(counterpartyService.getInfo(certificateId));
        } catch (Exception e) {
            log.error("查询交易方[{}]详情失败", certificateId, e);
            return SingleResponse.failure(ResponseCodeEnum.SYS_ERROR.getCode(), ResponseCodeEnum.SYS_ERROR.getMsg());
        }
    }

    @Operation(summary = "删除交易方")
    @DeleteMapping("delete/{counterpartyId}")
    public SingleResponse<Boolean> deleteCounterparty(@PathVariable Integer counterpartyId) {
        return SingleResponse.of(counterpartyService.deleteCounterparty(counterpartyId));
    }

    @Operation(summary = "导出交易方信息")
    @PostMapping("/export")
    public void export(@RequestBody ExportDTO dto, HttpServletResponse response) {
        try {
            counterpartyService.exportCounterparty(dto, response);
        } catch (Exception e) {
            log.error("导出交易方信息失败", e);
            FileResponseUtil.write(response, SingleResponse.failure(ResponseCodeEnum.ERROR.getCode(), ResponseCodeEnum.ERROR.getMsg()));
        }
    }
} 